#include <mutex>
using std::mutex;
#include <iostream>
using std::cout;
using std::endl;


/**
 * 使用模板实现
 * default 构造函数、copy 构造函数、析构函数
 * 构造函数要确保所有成员都被初始化，析构要确保所有成员都被释放
 * 共享，所以持有属性指针
 * release() - flag !!!
 * shared_ptr<T>& operator=(const shared_ptr<T>& sp)
 * T& operator*()、T* operator->
 * use_count()、get()
 * 
 * @tparam T 
 */
template <class T>
class shared_ptr{
public:
    explicit shared_ptr(T* ptr = nullptr): _ptr(ptr), _count(new int(1)), _pm(new mutex) {}
    shared_ptr(const shared_ptr<T>& sp): _ptr(sp._ptr), _count(sp._count), _pm(sp._pm){
        add_ref_count();
    }
    ~shared_ptr(){
        release();
    }

    shared_ptr<T>& operator=(const shared_ptr<T>& sp){
        if(_ptr != sp._ptr){
            release();
            _ptr    = sp._ptr;
            _count  = sp._count;
            _pm     = sp._pm;
            add_ref_count();
        }
        return *this;
    }

    T& operator*() const noexcept{ return *_ptr;}
    T* operator->() const noexcept{ return _ptr;}

public:
    int use_count() const noexcept{ return *_count;}
    T* get() const noexcept{ return _ptr;}

private:
    void add_ref_count() noexcept{
        _pm->lock();
        ++(*_count);
        _pm->unlock();
    }
    void release(){
        bool flag = false;
        _pm->lock();
        if(--(*_count) == 0){
            flag = true;
            delete _ptr;
            delete _count;
        }
        _pm->unlock();
        if(flag) delete _pm;
    }

private:
    T*      _ptr;
    int*    _count;
    mutex*  _pm;
};